package com.pointcircle.core.service;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.pointcircle.core.ApplicationContextHolder;
import com.pointcircle.core.entity.ApiPermission;
import com.pointcircle.core.repository.ApiPermissionRepository;
import com.pointcircle.core.web.annotation.ApiPermissionConfig;

@Service
public class ApiPermissionService {

	@Autowired
	private ApiPermissionRepository apiPermissionRepository;
	
	public void load() {
		Map<String, Object> map = ApplicationContextHolder
			.getApplicationContext().getBeansWithAnnotation(Controller.class);
		for(Map.Entry<String, Object> entry : map.entrySet()) {
			Object bean = entry.getValue();
			Class<?> clz = bean.getClass();
			Class<?> controllerClz = clz.getSuperclass();
			RequestMapping baseRequestMapping = AnnotationUtils.findAnnotation(clz, RequestMapping.class);
			ApiPermissionConfig baseApiPermissionConfig = AnnotationUtils.getAnnotation(controllerClz, ApiPermissionConfig.class);
			List<Method> methods = MethodUtils.getMethodsListWithAnnotation(controllerClz, ApiPermissionConfig.class);
			for(Method method : methods) {
				ApiPermissionConfig apiPermissionConfig = AnnotationUtils.getAnnotation(method, ApiPermissionConfig.class);
				if(apiPermissionConfig != null) {
					RequestMapping requestMapping = AnnotationUtils.getAnnotation(method, RequestMapping.class);
					String httpMethod = "GET";
					for(RequestMethod requestMethod : requestMapping.method()) {
						if(requestMethod == RequestMethod.POST) {
				      		httpMethod = "POST";
				       		break;
				      	}
				    }
				    PostMapping postMappingClz = AnnotationUtils.getAnnotation(method, PostMapping.class);
				    GetMapping getMappingClz = AnnotationUtils.getAnnotation(method, GetMapping.class);
				    String[] pathes = requestMapping.path();
				    if(postMappingClz != null) {
				    	pathes = ArrayUtils.addAll(pathes, postMappingClz.path());
				    	httpMethod = "POST";
				    }
				    if(getMappingClz != null) {
				        pathes = ArrayUtils.addAll(pathes, getMappingClz.path());
				        httpMethod = "GET";
				    }
				    String url = "/" + (baseRequestMapping == null ? "" : baseRequestMapping.value()[0]) 
				    	+ "/" + pathes[0];
				    url = RegExUtils.replaceAll(url, "/+", "/");
				    String api = httpMethod + " " + url;
				    String permission = "api:" + (baseApiPermissionConfig == null ? "" : baseApiPermissionConfig.value() + ":")
				    	+ apiPermissionConfig.value();
				    url = RegExUtils.replaceAll(url, ":+", "/");
				    if(apiPermissionRepository.findByApiAndPermission(api, permission).size() == 0) {
				    	ApiPermission apiPermission = new ApiPermission();
				    	apiPermission.setApi(api);
				    	apiPermission.setPermission(permission);
				    	apiPermissionRepository.saveAndFlush(apiPermission);
				    }
				}
			}
		}
	}
}
